#
# This file is a part of the open-eBackup project.
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at
# http://mozilla.org/MPL/2.0/.
#
# Copyright (c) [2024] Huawei Technologies Co.,Ltd.
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#

from common.logger import Logger
from db2.comm.const import Db2Const, Db2CmdFormat
from db2.comm.util.param_util import Db2ParamUtil
from db2.comm.util.single_util import SingleUtil
from db2.restore.hadr.hadr_parse_restore_params import HadrParseRestoreParams
from db2.restore.hadr.hadr_restore_service import HadrRestoreService

LOGGER = Logger().get_logger(filename="db2.log")


class HadrTsRestoreService(HadrRestoreService):
    def __init__(self, parse_params_obj: HadrParseRestoreParams):
        super().__init__(parse_params_obj)
        self.local_node = {}

    def exec_ts_full_restore(self):
        logtarget = self.get_logtarget_bind_path()
        copies = Db2ParamUtil.parse_copies(self.parse_param.param_dict)
        full_copy_path = Db2ParamUtil.get_full_copy_path(copies, job_id=self.parse_param.job_id)
        path = Db2ParamUtil.get_copy_path_info(self.parse_param.param_dict)
        full_bak_time = self.parse_param.get_restore_time(path[0])
        ts_names_str = self.parse_param.get_restore_ts()
        log_target_cmd = f"logtarget {logtarget} "
        restore_ts_cmd = Db2CmdFormat.TS_RESTORE.format(self.os_user, self.db_name, ts_names_str, "", full_copy_path,
                                                        full_bak_time, log_target_cmd)
        try:
            SingleUtil.execute_restore_ts(restore_ts_cmd)
        except Exception as exception_str:
            LOGGER.error(exception_str, exc_info=True)
            return False
        return True

    def exec_ts_incr_restore(self):
        logtarget = self.get_logtarget_bind_path()
        path = Db2ParamUtil.get_copy_path_info(self.parse_param.param_dict)
        path.insert(0, path[-1])
        ts_names_str = self.parse_param.get_restore_ts()
        restore_num = len(path)
        for idx, tmp_restore_copy in enumerate(path):
            # 只在最后一次restore时提取日志
            log_target_cmd = f"logtarget {logtarget} " if idx == (restore_num - 1) else ""
            copy_path = self.parse_param.get_data_path(tmp_restore_copy)
            tmp_copy_timestamp = self.parse_param.get_restore_time(tmp_restore_copy)
            restore_ts_cmd = Db2CmdFormat.TS_RESTORE.format(self.os_user, self.db_name, ts_names_str,
                                                            Db2Const.INCREMENTAL, copy_path,
                                                            tmp_copy_timestamp, log_target_cmd)
            try:
                SingleUtil.execute_restore_ts(restore_ts_cmd)
            except Exception as exception_str:
                LOGGER.error(exception_str, exc_info=True)
                return False
        return True

    def exec_ts_diff_restore(self):
        logtarget = self.get_logtarget_bind_path()
        path = Db2ParamUtil.get_copy_path_info(self.parse_param.param_dict)
        # 手动恢复顺序：差异->全量->差异
        path.insert(0, path[-1])
        ts_names_str = self.parse_param.get_restore_ts()
        restore_num = len(path)
        for idx, tmp_restore_copy in enumerate(path):
            # 只在最后一次restore时提取日志
            log_target_cmd = f"logtarget {logtarget} " if idx == (restore_num - 1) else ""
            copy_path = self.parse_param.get_data_path(tmp_restore_copy)
            tmp_copy_timestamp = self.parse_param.get_restore_time(tmp_restore_copy)
            restore_ts_cmd = Db2CmdFormat.TS_RESTORE.format(self.os_user, self.db_name, ts_names_str,
                                                            Db2Const.INCREMENTAL, copy_path, tmp_copy_timestamp,
                                                            log_target_cmd)
            try:
                SingleUtil.execute_restore_ts(restore_ts_cmd)
            except Exception as exception_str:
                LOGGER.error(exception_str, exc_info=True)
                return False
        return True

    def exec_ts_rollforward(self):
        logtarget = self.get_logtarget_bind_path()
        ts_names_str = self.parse_param.get_restore_ts()
        rollforward_cmd = Db2CmdFormat.TS_ROLL.format(self.os_user, self.db_name, ts_names_str, logtarget)
        try:
            SingleUtil.execute_rollforward_ts(rollforward_cmd)
        except Exception as exception_str:
            LOGGER.error(exception_str, exc_info=True)
            return False
        return True

    def exec_ts_offline_backup(self):
        ts_names_str = self.parse_param.get_restore_ts()
        ts_backup_cmd = Db2CmdFormat.TS_OFFLINE_BACKUP.format(self.os_user, self.db_name, ts_names_str)
        try:
            self.execute_cmd_without_echo(ts_backup_cmd)
        except Exception as exception_str:
            LOGGER.error(exception_str, exc_info=True)
            return False
        return True
